/*===========================================================================
  Copyright (C) 2014 by the Okapi Framework contributors
-----------------------------------------------------------------------------
  This library is free software; you can redistribute it and/or modify it 
  under the terms of the GNU Lesser General Public License as published by 
  the Free Software Foundation; either version 2.1 of the License, or (at 
  your option) any later version.

  This library is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
  General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License 
  along with this library; if not, write to the Free Software Foundation, 
  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

  See also the full LGPL text here: http://www.gnu.org/copyleft/lesser.html
===========================================================================*/

package net.sf.okapi.v2.common.om.impl;

import java.util.LinkedHashMap;
import java.util.UUID;

import net.sf.okapi.v2.common.U;
import net.sf.okapi.v2.common.exceptions.InvalidParameterException;
import net.sf.okapi.v2.common.om.IGroup;
import net.sf.okapi.v2.common.om.IGroupOrUnit;
import net.sf.okapi.v2.common.om.ISubDocument;
import net.sf.okapi.v2.common.om.ITextUnit;

/**
 * Implements {@link ISubDocument}.
 */
public class SubDocument implements ISubDocument {

	private String id;
	private LinkedHashMap<String, IGroupOrUnit> items;

	/**
	 * Creates a new {@link ISubDocument}.
	 * @param id the id of this new sub-document (must not be empty, use null for an auto-generated UUID value).
	 */
	public SubDocument (String id) {
		if ( id == null ) {
			id = UUID.randomUUID().toString();
		}
		else if ( id.isEmpty() ) {
			throw new InvalidParameterException("Id must not be empty.");
		}
		this.id = id;
		items = new LinkedHashMap<>();
	}
	
	@Override
	public String getId () {
		return id;
	}

	@Override
	public void setId (String id) {
		if ( U.isNoE(id) ) {
			throw new InvalidParameterException("Id must not be null or empty.");
		}
		this.id = id;
	}

	@Override
	public ITextUnit add (ITextUnit unit) {
		items.put("u"+unit.getId(), unit);
		return unit;
	}

	@Override
	public IGroup add (IGroup group) {
		items.put("g"+group.getId(), group);
		return group;
	}
	
	@Override
	public Iterable<IGroupOrUnit> iterator (boolean recursive) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ITextUnit getUnit (String id) {
		// Try at this level
		ITextUnit unit = (ITextUnit)items.get("u"+id);
		if ( unit != null ) return unit;
		// Else: try recursively
		for ( IGroupOrUnit item : items.values() ) {
			if ( !item.isUnit() ) {
				unit = (ITextUnit)((IGroup)item).getUnit(id);
				if ( unit != null ) return unit;
			}
		}
		// Not found
		return null;
	}
	
	@Override
	public IGroup getGroup (String id) {
		// Try at this level
		IGroup group = (IGroup)items.get("g"+id);
		if ( group != null ) return group;
		// Else: try recursively
		for ( IGroupOrUnit item : items.values() ) {
			if ( !item.isUnit() ) {
				group = (IGroup)((IGroup)item).getGroup(id);
				if ( group != null ) return group;
			}
		}
		// Not found
		return null;
	}

	@Override
	public IGroupOrUnit get (String id) {
		// Try at this level
		if ( items.containsKey("u"+id) ) return items.get("u"+id);
		if ( items.containsKey("g"+id) ) return items.get("g"+id);
		// Else: try recursively
		for ( IGroupOrUnit item : items.values() ) {
			if ( !item.isUnit() ) {
				IGroupOrUnit gou = ((IGroup)item).get(id);
				if ( gou != null ) return gou;
			}
		}
		// Not found
		return null;
	}

}
